package com.vcaresolution.logistic.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.vcaresolution.logistic.form.ShippingbillForm;
import com.vcaresolution.logistic.form.ShippingcontainersForm;
import com.vcaresolution.logistic.pojo.Codetable;
import com.vcaresolution.logistic.pojo.Container;
import com.vcaresolution.logistic.pojo.Jobregister;
import com.vcaresolution.logistic.pojo.Shippingbill;
import com.vcaresolution.logistic.pojo.Shippingcontainers;
import com.vcaresolution.logistic.to.ShippingbillDetailsTO;
import com.vcaresolution.logistic.to.ShippingbillTO;
import com.vcaresolution.logistic.util.ApplicationConstants;
import com.vcaresolution.util.Utils;

@Service
public class ShippingbillServiceImpl extends BaseService implements ShippingbillService{

	private Shippingbill populateShippingbillPojo(ShippingbillForm shippingbillForm){
		Shippingbill shippingbill = new Shippingbill();
		BeanUtils.copyProperties(shippingbillForm, shippingbill);
		
		return shippingbill;
	}
	
	private Shippingcontainers populateShippingcontainersPojo(ShippingcontainersForm shippingcontainersForm){
		
		Shippingcontainers shippingcontainers = new Shippingcontainers();
		BeanUtils.copyProperties(shippingcontainersForm, shippingcontainers);
		
		return shippingcontainers;
	}
	
	@Override
	@Transactional
	public void add(ShippingbillForm shippingbillForm) {
		
		Shippingbill shippingbill = populateShippingbillPojo(shippingbillForm);
		
		if(shippingbill.getSbillno() != null && shippingbill.getSbillno().intValue() > 0){
			
			Boolean checkForExistShippingBillNumber = checkForExistShippingBillNumber(shippingbill.getSbillno());
			
			if(!checkForExistShippingBillNumber){
				
				shippingbill.setJobregister(getDaoFactory().getUtilityDAO().findById(Jobregister.class, shippingbillForm.getJobnoid()));
				shippingbill.setCodetableByDirecthubid(getDaoFactory().getCodetableDAO().findById(Codetable.class, shippingbillForm.getDirecthubid()));
				shippingbill.setCodetableByIncotermsid(getDaoFactory().getCodetableDAO().findById(Codetable.class, shippingbillForm.getIncotermsid()));
				shippingbill.setCodetableByCurrencyid(getDaoFactory().getCodetableDAO().findById(Codetable.class, shippingbillForm.getCurrencyid()));
				
				shippingbill.setCreationdate(Utils.getCurrentDate());
				
				getDaoFactory().getUtilityDAO().add(shippingbill);
				
			}
		}
		
		//Setting Shippingcontainers object and inserting into Database
		Shippingcontainers shippingcontainers = populateShippingcontainersPojo(shippingbillForm.getShippingcontainersForm());
		
		if(shippingbillForm.getShippingcontainersForm().getNetweightType() != null && 
				shippingbillForm.getShippingcontainersForm().getNetweightType() > 0){
			
			shippingcontainers.setCodetableByNetweightid(getDaoFactory().getCodetableDAO().findById
					(Codetable.class, shippingbillForm.getShippingcontainersForm().getNetweightType()));
		}
		
		if(shippingbillForm.getShippingcontainersForm().getGrossweightType() != null &&
				shippingbillForm.getShippingcontainersForm().getGrossweightType() > 0){
			
			shippingcontainers.setCodetableByGrossweightid(getDaoFactory().getCodetableDAO().findById
					(Codetable.class, shippingbillForm.getShippingcontainersForm().getGrossweightType()));
		}
		
		shippingcontainers.setCodetableByPackagestypeid(getDaoFactory().getCodetableDAO().findById
														(Codetable.class, shippingbillForm.getShippingcontainersForm().getPackagestypeid()));
		
		//TODO what happen when sbillno is more than one
		List<Shippingbill> shippingbillList = getDaoFactory().getUtilityDAO().findByCondition
				(Shippingbill.class, Utils.getEqExpressionList("sbillno", shippingbillForm.getSbillno()));
		
		shippingcontainers.setShippingbill(shippingbillList.get(0));
		
		shippingcontainers.setContainer(getDaoFactory().getUtilityDAO().findById
														(Container.class, shippingbillForm.getShippingcontainersForm().getContainerid()));
		
		getDaoFactory().getUtilityDAO().add(shippingcontainers);
	}

	@Override
	@Transactional
	public void update(ShippingbillForm shippingbillForm) {
		Shippingbill shippingbill = populateShippingbillPojo(shippingbillForm);
		
		shippingbill.setJobregister(getDaoFactory().getUtilityDAO().findById(Jobregister.class, shippingbillForm.getJobnoid()));
		shippingbill.setCodetableByDirecthubid(getDaoFactory().getCodetableDAO().findById(Codetable.class, shippingbillForm.getDirecthubid()));
		shippingbill.setCodetableByIncotermsid(getDaoFactory().getCodetableDAO().findById(Codetable.class, shippingbillForm.getIncotermsid()));
		shippingbill.setCodetableByCurrencyid(getDaoFactory().getCodetableDAO().findById(Codetable.class, shippingbillForm.getCurrencyid()));
		
		getDaoFactory().getUtilityDAO().update(shippingbill);
		
		//Setting Shippingcontainers object and updating into Database
		Shippingcontainers shippingcontainers = populateShippingcontainersPojo(shippingbillForm.getShippingcontainersForm());
		
		if(shippingbillForm.getShippingcontainersForm().getNetweightType() != null && 
				shippingbillForm.getShippingcontainersForm().getNetweightType() > 0){
			
			shippingcontainers.setCodetableByNetweightid(getDaoFactory().getCodetableDAO().findById
					(Codetable.class, shippingbillForm.getShippingcontainersForm().getNetweightType()));
		}
		
		if(shippingbillForm.getShippingcontainersForm().getGrossweightType() != null &&
				shippingbillForm.getShippingcontainersForm().getGrossweightType() > 0){
			
			shippingcontainers.setCodetableByGrossweightid(getDaoFactory().getCodetableDAO().findById
					(Codetable.class, shippingbillForm.getShippingcontainersForm().getGrossweightType()));
		}
		
		shippingcontainers.setCodetableByPackagestypeid(getDaoFactory().getCodetableDAO().findById
														(Codetable.class, shippingbillForm.getShippingcontainersForm().getPackagestypeid()));
		
		shippingcontainers.setShippingbill(getDaoFactory().getUtilityDAO().findById
											(Shippingbill.class, shippingbillForm.getSbid()));
		
		shippingcontainers.setContainer(getDaoFactory().getUtilityDAO().findById
														(Container.class, shippingbillForm.getShippingcontainersForm().getContainerid()));
		
		getDaoFactory().getUtilityDAO().update(shippingcontainers);
	}

	@Override
	@Transactional
	public void delete(ShippingbillForm shippingbillForm) {
		getDaoFactory().getUtilityDAO().delete(populateShippingbillPojo(shippingbillForm));
	}

	@Override
	@Transactional
	public ShippingbillTO findById(Serializable sbID,Serializable shippingContainerId) {
		
		//Getting Data for ShippingBillDetails And Containers
		Shippingbill shippingbill = getDaoFactory().getShippingDAO().getShippingBillDetailsAndContainers(sbID, shippingContainerId);
		
		ShippingbillTO shippingBillTO = new ShippingbillTO();
		if(shippingbill != null){
			
			BeanUtils.copyProperties(shippingbill, shippingBillTO);
			
			shippingBillTO.setDirecthubid(shippingbill.getCodetableByDirecthubid().getCodetableid());
			shippingBillTO.setIncotermsid(shippingbill.getCodetableByIncotermsid().getCodetableid());
			
			shippingBillTO.setCurrency(shippingbill.getCodetableByCurrencyid().getFormvalue());
			shippingBillTO.setCurrencyid(shippingbill.getCodetableByCurrencyid().getCodetableid());
			
			shippingBillTO.setJobnoid(shippingbill.getJobregister().getJobnoid());
			
			//Setting shippingcontainerses Details
			Set shippingcontainerses = shippingbill.getShippingcontainerses();
			
			Iterator iterator = shippingcontainerses.iterator();
			
			while(iterator.hasNext()){
				
				Shippingcontainers shippingcontainers = (Shippingcontainers) iterator.next();
				
				if(shippingcontainers != null){
					
					//Getting only matching container id details for Edit object
					if(shippingcontainers.getShippingcontainerid().equals(shippingContainerId)){
						
						if(shippingBillTO.getShippingcontainersForm() == null){
							shippingBillTO.setShippingcontainersForm(new ShippingcontainersForm());
						}
						
						shippingBillTO.getShippingcontainersForm().setShippingcontainerid(shippingcontainers.getShippingcontainerid());
						shippingBillTO.getShippingcontainersForm().setContainerid(shippingcontainers.getContainer().getContainerid());
						shippingBillTO.getShippingcontainersForm().setPackagestypeid(shippingcontainers.getCodetableByPackagestypeid().getCodetableid());
						shippingBillTO.getShippingcontainersForm().setNetweightType(shippingcontainers.getCodetableByNetweightid().getCodetableid());
						shippingBillTO.getShippingcontainersForm().setGrossweightType(shippingcontainers.getCodetableByGrossweightid().getCodetableid());
						
						shippingBillTO.getShippingcontainersForm().setNoofpackages(shippingcontainers.getNoofpackages());
						shippingBillTO.getShippingcontainersForm().setNetweight(shippingcontainers.getNetweight());
						shippingBillTO.getShippingcontainersForm().setGrossweight(shippingcontainers.getGrossweight());
						shippingBillTO.getShippingcontainersForm().setCbm(shippingcontainers.getCbm());
						shippingBillTO.getShippingcontainersForm().setCargoreceiveddate(shippingcontainers.getCargoreceiveddate());
					}
				}
			}
			
		}
		
		return shippingBillTO; 
	}

	@Override
	@Transactional
	public List<ShippingbillTO> findByAll() {
		
		List<Shippingbill> shippingbillList = getDaoFactory().getUtilityDAO().findByAll(Shippingbill.class);
		
		List<ShippingbillTO> shippingbillFormList = new ArrayList<ShippingbillTO>();
		
		if( shippingbillList != null && !shippingbillList.isEmpty() ){
			ShippingbillTO shippingBillTO = null;
			for(Shippingbill shippingbill: shippingbillList){
				shippingBillTO = new ShippingbillTO();
				
				shippingBillTO.setCurrency(shippingbill.getCodetableByCurrencyid().getFormvalue());
				
				BeanUtils.copyProperties(shippingbill, shippingBillTO);
				shippingbillFormList.add(shippingBillTO);
			}
		}	
		return shippingbillFormList;
	}

	@Override
	@Transactional
	public List<ShippingbillTO> findByAll(Serializable jobId) {
		
		//Getting Data for ShippingBills for selected JOB id
		List<Shippingbill> shippingbillList = getDaoFactory().getUtilityDAO().findByCondition(Shippingbill.class, Utils.getEqExpressionList("jobregister.jobnoid", jobId));
		
		List<ShippingbillTO> shippingbillFormList = new ArrayList<ShippingbillTO>();
		
		if( shippingbillList != null && !shippingbillList.isEmpty() ){
			ShippingbillTO shippingBillTO = null;
			for(Shippingbill shippingbill: shippingbillList){
				
				//Getting set for shippingContainers from Shippingbill
				Set shippingContainersSet = shippingbill.getShippingcontainerses();
				
				//Iterating shippingContainersSet
				Iterator iterator = shippingContainersSet.iterator();
				while(iterator.hasNext()){
					
					Shippingcontainers shippingcontainers = (Shippingcontainers) iterator.next();
					
					//Setting shippingBillTO object
					shippingBillTO = new ShippingbillTO();
					shippingBillTO.setCurrency(shippingbill.getCodetableByCurrencyid().getFormvalue());
					BeanUtils.copyProperties(shippingbill, shippingBillTO);
					
					//Setting shippingcontainerses Details
					if(shippingBillTO.getShippingcontainersForm() == null){
						shippingBillTO.setShippingcontainersForm(new ShippingcontainersForm());
					}
					
					if(shippingcontainers != null){
						
						BeanUtils.copyProperties(shippingcontainers, shippingBillTO.getShippingcontainersForm());
						
						shippingBillTO.getShippingcontainersForm().setPackageType(ApplicationConstants.CODETABLELVALUES.get(shippingBillTO.
								getShippingcontainersForm().getCodetableByPackagestypeid().getCodetableid()));

						shippingBillTO.getShippingcontainersForm().setContainerType(ApplicationConstants.CODETABLELVALUES.get(shippingBillTO.
								getShippingcontainersForm().getContainer().getContainertypeid()));
					}
					
					//Adding into List of shippingbillForm
					shippingbillFormList.add(shippingBillTO);
				}
				
			}
		}	
		return shippingbillFormList;
	}

	/**
	 * This method check whether ShppingBill number and cotainerID is exist with association or not.
	 */
	/*
	 * (non-Javadoc)
	 * @see com.vcaresolution.logistic.service.ShippingbillService#checkForShippingBillNumber(java.io.Serializable, java.io.Serializable)
	 */
	@Override
	@Transactional
	public Boolean checkForExistShippingBillNumberAndContainer	(Serializable sbillno,Serializable containerid) {
		
		return getDaoFactory().getShippingDAO().checkForExistShippingBillNumberAndContainer(sbillno, containerid);
		
	}

	/**
	 * This method populate Shipping Bill details
	 */
	/*
	 * (non-Javadoc)
	 * @see com.vcaresolution.logistic.service.ShippingbillService#populateShippingBill(java.lang.String)
	 */
	@Override
	@Transactional
	public List<ShippingbillDetailsTO> populateShippingBill(String sbillno) {
		
		List<Shippingbill> shippingbillList = getDaoFactory().getShippingDAO().populateShippingBill(sbillno);
		
		List<ShippingbillDetailsTO> shippingbillFormList = new ArrayList<ShippingbillDetailsTO>();
		
		if( shippingbillList != null && !shippingbillList.isEmpty() ){
			
			ShippingbillDetailsTO shippingbillDetailsTO = null;
			for(Shippingbill shippingbill: shippingbillList){
				shippingbillDetailsTO = new ShippingbillDetailsTO();
				shippingbillDetailsTO.setCurrencyid(shippingbill.getCodetableByCurrencyid().getCodetableid());
				shippingbillDetailsTO.setDirecthubid(shippingbill.getCodetableByDirecthubid().getCodetableid());
				shippingbillDetailsTO.setIncotermsid(shippingbill.getCodetableByIncotermsid().getCodetableid());
				
				shippingbillDetailsTO.setSbilldateString(Utils.convertDateObjectToDDMMYYYY(shippingbill.getSbilldate()));
				shippingbillDetailsTO.setInvoicedateString(Utils.convertDateObjectToDDMMYYYY(shippingbill.getInvoicedate()));
				
				shippingbillDetailsTO.setSbillNo(String.valueOf(shippingbill.getSbillno()));
				
				BeanUtils.copyProperties(shippingbill, shippingbillDetailsTO);
				
				//Adding into List of shippingbillForm
				shippingbillFormList.add(shippingbillDetailsTO);
			}
		}
		
		return shippingbillFormList;
	}

	/**
	 * This method checks whether Shipping bill number is presnt or not
	 */
	/*
	 * (non-Javadoc)
	 * @see com.vcaresolution.logistic.service.ShippingbillService#checkForExistShippingBillNumber(java.io.Serializable)
	 */
	@Override
	public Boolean checkForExistShippingBillNumber(Serializable sbillno) {
		
		//Getting List for selected sbillno 
		List<Shippingbill> shippingBillList = getDaoFactory().getUtilityDAO().findByCondition(Shippingbill.class, 
						Utils.getEqExpressionList("sbillno", sbillno));
		
		if(shippingBillList != null && !shippingBillList.isEmpty()){
			
			return Boolean.TRUE;
		
		} else {
			
			return Boolean.FALSE;
		}
		
	}
}